home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Belgian Amiga Club - ADF Collection
/
BS1 part 34.zip
/
BS1 part 34
/
FredFish PD 307.adf
/
Samp
/
SAMPlib.doc
< prev
next >
Wrap
Text File
|
1990-01-13
|
19KB
|
395 lines
This is the document for the dissidents' samp.library 1.0 © 1989. Set your
editor's TAB width to 3.
«««««««««««««« WHAT THE HELL IS SAMP? »»»»»»»»»»»»
(or "If it doesn't have anything to do with video, what good is it?")
The dissidents' samp.library is a library used to load and save SAMP files.
SAMP is an IFF file format used to store any resolution audio data. This format
is used in dissidents' Midi Sample Wrench, a 16 bit audio waveform editing
program for the Amiga, and is currently under consideration for adoption by
CATS. The samp.library will allow you to write applications that can save
and retrieve audio data saved in the SAMP format. For a detailed spec of the
SAMP format, consult the SAMP.doc file.
The samp.library is written entirely in 68000 assembly for speed and small
size. Distributed with the library are C and assembly Include files and example
applications, as well as a utility to convert 8SVX files to SAMP.
««««««««««««««««« COPYRIGHT NOTICE »»»»»»»»»»»»»»»»»»
The samp.library and ToSAMP conversion utility are copyright by dissidents
software. These two files may be used by and freely distributed with any
application, commercial or otherwise, although copyright is retained exclu-
sively by dissidents, and the files must not be modified in any way. In
addition, the following files are copyright by dissidents, and may only be
distributed on disks which are freely-distributable or for which a nominal
charge to cover media and shipping is the only consumer cost:
1). SAMPlib.doc
2). SAMP.doc
3). ToSAMP.asm
4). Exam.c
5). Exam.asm
6). SAMP.i
7). SAMP.h
8). SAMPInterface.asm
All copyright notices must remain intact.
«««««««««««««««« CURRENT LIMITATIONS »»»»»»»»»»»»»»»»
The library does not support loading/saving SAMP files inside of a CAT or
LIST, nor does it currently support Continuation files or NumOfChans > 4.
Due to memory considerations, the library can only be servicing one task
at any given moment (though several tasks may simultaneously open the library).
««««««««««««««««« DATA STRUCTURES »»»»»»»»»»»»»»»»»
Before you open and use the samp.library, you must create a few structures
and variables from which the library can load/save data. The most important
structure is is the SampleHeader64 structure. It is used to hold information
about 1 waveform such as its size, OneShotStart and LoopStart addresses, Root
Note, and velocity table. Each waveform that is loaded must have its own 64
byte SampleHeader64 structure. Furthermore, all the SampleHeader64 structures
must be contiguous in memory. For this reason, an application should allocate
the proper number of SampleHeader64 structures before actually loading the
waveform data. This can be done by either of the following procedures:
1). Determine the maximum # of waves that the application can load, and
declare an array of this many SampleHeader64 structures.
(The C example takes this approach).
2). After opening a file (via OpenSampRead) and examining the MHDR's
NumOfWaves, allocate a block of mem with size = sizeofSampleHeader64
* NumOfWaves.
The string buffers for the waves' names must also be contiguous in memory.
For this reason, your application must decide upon the maximum length of each
name, and allocate an appropriately sized mem block. On the other hand, you
may forego allocating any string buffers, in which case the library will ignore
loading the waves' names.
Finally, a pointer to a TransposeNode must be declared (and initially set
to zero). A TransposeNode is a structure that the library will create for
every different sampleRate in a SAMP file. These structures are all linked
into a list to which your variable points. A TransposeNode contains a transpose
table as described in the SAMP doc.
«««««««««««««««««« LIBRARY STRUCTURES »»»»»»»»»»»»»»»»
When you open a SAMP file to read or write, you gain exclusive access to
the samp.library's structures until you close the file. One structure is a
SAMPInfo structure. This contains an imbedded MHDR chunk. When you open a
SAMP for reading via OpenSampRead(), the SAMP's MHDR is loaded into the library
SAMPInfo's MHDR. So, you can examine the file's NumOfWaves, NumOfChans,
Format, etc before loading any wave data. The SAMPInfo also contains fields to
store pointers to (addresses of) functions within your application. These
functions will be called at certain times by the library's read/write routines.
For example, you can supply a pointer to a function which will be called by
the library's ReadWaves() for every wave's FATK data handling. The SAMPInfo
also contains fields to specify the maximum allowed length of a wave's name,
the type of mem into which the wave data will be loaded, and Seek() offsets
from the beginning of the file to various chunks.
The library also has a waveHeader structure as described in the SAMP doc.
This structure is used by ReadWaves() and WriteWaves() to hold data per each
wave read/written.
«««««««««««««««««««« OPENING THE LIBRARY »»»»»»»»»»»»»»»»»»»
The samp.library file must be copied to the libs drawer of your boot disk.
Then, any application may open and use the library via a call to Exec's
OpenLibrary(). The current version of samp is 0. The library is closed via
Exec's CloseLibrary(). C applications must be linked with the module
SAMPInterface.asm
(which itself must be assembled by your C compiler's assembler).
««««««««««««««««««««« THE LIBRARY FUNCTIONS »»»»»»»»»»»»»»»»»»
Here are descriptions and calling procedures for the library functions:
*************************** OpenSampRead *****************************
This routine must be called first in order to read in a SAMP file and
perform operations on it via other library routines such as LoadNames,
LoadPlaymap, MixPlaymap, and ReadWaves. It opens the file, determines
if it is a SAMP file that the library can read, and prevents other tasks
from using the library until the file is processed and closed.
This is passed the name of the SAMP file to be opened (a NULL-terminated
string). Also, you may pass a pointer to a function which the library should
call for unknown chunks, or instead pass in 0. The library understands
"BODY", "AUTH", "ANNO", "NAME", "MHDR" and "(c) " chunks. If you pass a 0,
it will ignore all other chunks. If you pass a pointer to your own function,
it will call your function as so:
flag = UnknownChunk(SAMPInfo, SeekOffset, ChunkSize ID);
a4 d4 d2 d0
If you return a 1, then the OpenSampRead terminates and closes the file.
A 0 allows OpenSampRead to continue.
For more details, see the section "PROCESSING UNKNOWN CHUNKS".
OpenSampRead() returns the address of the library's SAMPInfo structure
or 0 if an error. The z-flag is cleared for error (bne Error), set otherwise.
An error may be caused by some other task already using the library, failure
to open the requested file, the requested file is not a SAMP file, or the BODY
for this SAMP file cannot be located within this file (i.e. will not support
Continuation files). For C programmers, the exact error number is returned
in a variable called SAMPError (which is a global in the module
SampInterface.asm). For assembly programmers, the exact error number is
returned in d1.
SAMPInfo = OpenSampRead( Filename, UnKnownVector );
d0 d1 a0
***************************** CloseSamp *******************************
Closes a SAMP file that was opened for reading or writing, and frees the
library for other tasks to use. This must be called after you have successfully
opened a SAMP file (via OpenSampRead or OpenSampWrite), and are finished
processing it.
CloseSamp();
***************************** ReadWaves *********************************
#define nameSize 20
total = ReadWaves(offsetWave,totalWaves,nameBuffer[offsetWave][nameSize],SampleHeader64[offsetWave]);
d0 d6 d7 a2 a3
Loads the specified range of waves within the SAMP file between offsetWave
and offsetWave+totalWaves. offsetWave is the first wave to start loading
(with the first wave in the SAMP file being wave #0). Loads them starting at
the passed SampleHeader64. Also loads the names for these waves starting at
nameBuffer unless passed a NULL. Before calling ReadWaves, you should
set the library SAMPInfo's MaxChars variable to the max # of chars each
nameBuffer can hold. The default is 20 bytes. All names are padded out with
spaces and NULL-terminated.
Also, you should set the SAMPInfo's ATAKvector, RLSEvector, FATKvector,
FRLSvector, USERvector, and EXTRAvector to point to any routines you want the
library to call per wave. If you don't, the default is for the library to
ignore FATK, FRLS, and USER data, and to read/reformat ATAK and RLSE EGPoints
into the SampleHeader64's envelope fields.
offsetWave is specified from zero (i.e. a value of zero won't skip any waves
in the file. A 2 will skip the first 2 waves in the file and start loading the
3rd wave into SampleHeader1.) For totalWaves = 1, only 1 wave is loaded.
This returns the number of waves actually loaded (0 if none). Sets
z-flag for success, cleared for error. For C programmers, the exact error
number is returned in a variable called SAMPError. For assembly programmers,
the exact error number is returned in d1.
Each wave's SampleHeader64 structure has an TransTable field. ReadWaves()
places each wave's sampleRate in this field. Later, you can extract the value
from this field when making the transpose tables, and rewrite the field with
a pointer to the ORIGINAL pitch of the table. See the C example.
The library calls your ATAK, RLSE, FATK, FRLS, or USER vector only if a
wave has data. In other words, if a wave doesn't have any FRLS EGPoints,
then the library skips calling your FRLS vector when loading that wave.
The library calls your EXTRA vector AFTER each wave's 80 byte waveHeader
and sample data are read in. This vector is useful for getting the library
waveHeader's midiSampNum, loopType, and instrumType if you wish to use/store
this data.
Your vectors are passed the lib's SAMPInfo and waveHeader, the current
SampleHeader64 address (a pointer to a SampleHeader64), and waveNumber
(minus offsetWave).
They should return an abort flag (1 = Abort read, 0 = continue). For
example, the library calls your FATK routine as so:
flag = FATKroutine(waveHeader, SAMPInfo, SampleHeader, waveNumber);
d0 a5 a4 a3 d5
When reading a SAMP, you should either read or seek past any data from
within an ATAK, RLSE, FATK, FRLS, or USER vector. When the library calls your
ATAK, RLSE, FATK, FRLS, or USER vector, the DOS file position will be at the
expected data within the SAMP file. In other words, when the library calls
your FATK vector, the file position will be at the wave's FATK data (if there
is any). When the library calls your USER vector, the file position will be
at the wave's USER data (if any). The library passes your vector the size of
the data (in bytes). Your vector must either read exactly this many bytes of
data, or Seek() forward this many bytes from the current position. In other
words, when your vector returns, the new file position must be at the next
byte AFTER the expected data. If you Seek() somewhere else in the file, always
Seek() back to the point after the expected data before your vector returns.
*************************** LoadPlayMap ********************************
Checks each byte of the loaded PlayMap. For every wave number above or below
the wave range (offsetWave+1 to offsetWave+totalWaves) in the loaded PlayMap,
the application's destination PlayMap byte is left as is. Otherwise, the wave
number is set to
(SAMPInfo's NumOfWaves - offsetWave) + startWave
where startWave is the number of the SampleHeader where the first wave
was loaded in. (startWave and offsetWave both referenced from wave #0)
numOfChans is the # of channels for each midi note in the destination playMap.
LoadPlaymap simply zeros out the destination playMap first.
If totalWaves = 0, LoadPlaymap just zeros out the playMap and MixPlaymap
does nothing. In this case, offsetWave and startWave are ignored.
MixPlayMap(totalWaves,numOfChans,offsetWave,startWave,destPlayMap);
d0 d1 d6 d7 a0
*************************** MakeTransTable ***************************
Makes a TransposeNode for the passed sampleRate (in hz). The transpose table
will have the specified # of steps above and below the ORIGINAL_PITCH as
described by the upperRange and lowerRange values. This routine will
allocate and link the TransposeNode into the passed TList only if there
is not already a table for this sampleRate. Otherwise, returns ORIGPITCH
of the other table in order to avoid duplication. Returns a zero if not
enough mem to create a new table, or the passed sampleRate = 0.
TList holds the address of the first TransposeNode.
You may set the library's SAMPInfo's LowLimit and HighLimit fields
before calling this. Defaults are 500 and 127 respectively. These are the
limits between which the period values must range within the Transpose table.
If a period is outside these limits, then the Transpose table entry is set
to zero to indicate that the period is out of range. When playing back the
wave, it is then easy to determine if a certain transposition of a wave's
sample Rate results in a period out of range. The default limits are set for
normal DMA audio and should not be altered unless your program does non-DMA
audio output.
ORIGPITCHaddress = MakeTransTable(sampleRate,upperRange,lowerRange,&TList);
d0 d5 d6 d7 a2
***************************** OpenSampWrite ***************************
Opens the SAMP filename for writing. Must be called before using WriteMHDR,
WriteName, WriteChunk, or WriteWaves. Returns the address of the library's
SAMPInfo if success, or a zero if the file couldn't be created. Upon
successful return, application should set SAMPInfo's Format, PlayMode,
NumWaves, and NumOfChans. The defaults for these are 8 bit, INDEPENDENT,
0 waves, and 4 channels. z-flag cleared for error.
SAMPInfo=OpenSampWrite(fileName);
d0 d1
******************************* WriteMHDR ******************************
Writes out the SAMP and MHDR with SAMP header fileSize = 14+sizeOfPlayMap.
Adjusts your PlayMap bytes so that all wave numbers < startWave and > =
startWave+numWaves are set to 0. startWave is from 0 being the first wave.
Returns a 1 if success, 0 if an error.
BOOL WriteMHDR(startWave,playMap);
d0 d0 a0
******************************* WriteSampChunk ***************************
Writes out the passed ID, size (of data, not including header), and data.
Returns a 1 if success, 0 if an error.
BOOL = WriteSampChunk(ID,size,data);
d0 d0 d1 a0
****************************** WriteSampData ******************************
Writes out the data for the passed number of bytes and the passed data ptr.
This is commonly used by vector routines writing out FATK, FRLS, and USER
data when saving a wave. Returns a 1 if success, 0 if an error.
BOOL = WriteSampData(numOfBytes, dataPtr);
d0 d3 a0
****************************** WriteNames ********************************
Writes the NAME chunk. Uses SAMPInfo's NumWaves to determine how many wave
names to write. Passed the base of the first string buffer. Passed the size
of a string buffer. Ignores trailing spaces on each name.
Returns a 1 if success, 0 if an error.
BOOL WriteNames(bufsize, bufPtr);
d0 d0 a0
******************************* WriteWaves *****************************
BOOL WriteWaves(offsetWave,totalWaves,SampleHeader64[0],TList)
d0 d0 d1 a0 a1
Writes the specified range of waves between offsetWave and offsetWave +
totalWaves to the SAMP file. offsetWave is the first wave to start saving
(with the first SampleHeader64 being wave #0).
offsetWave is specified from zero (i.e. a value of zero won't skip any
SampleHeader64 structs. A 2 will skip the first 2 SampleHeader64s and start
saving the 3rd SampleHeader64 as wave #0.) For totalWaves = 1, only 1 wave
is saved.
totalWaves is the number of waves to save. If totalWaves = 0, it returns 1
and writes an "empty" BODY chunk.
TList holds the address of the first TTNode. (a C handle)
Before calling WriteWaves(), you should set the SAMPInfo's ATAKvector,
RLSEvector, FATKvector, FRLSvector, USERvector, and EXTRAvector to point to
any routines you want the library to call per wave. If you don't, the default
is for the library to write no FATK, FRLS, and USER data, and to write ATAK
and RLSE EGPoints based upon the SampleHeader64's envelope fields.
WriteWaves() calls your EXTRAvector BEFORE the each wave's 80 byte waveHeader
and data is written out. This vector is useful for setting the library
waveHeader's SampNum, LoopType, and InsType per wave.
Calls ATAK, RLSE, FATK, FRLS vectors to write out Amplifier/Filter EGPoints,
and USERvector to write User Data.
The vectors are passed the lib's SAMPInfo and waveHeader, and the current
SampleHeader. The vectors should return an abort flag (1 = Abort write, 0 =
continue). For example, the library calls your FATK routine as so:
flag = FATKroutine(waveHeader, SAMPinfo, SampleHeader);
d0 a5 a4 a3
You must set the waveHeader's size fields to the number of bytes in the
data written out. For example, if your USER vector writes out 40 bytes of
data, set the waveHeader's USERsize to 40. (You should also set the USERtype).
************************** SAMPErrorMsg ****************************
When passed the error number (as returned by OpenSampRead for example),
this returns the address of a NULL-terminated string describing the error.
This is suitable for informing the user of any possible errors. For asm
programmer's certain lib routines return a error number in d1. For C pro-
grammer's, the error is stored in a variable called SAMPError.
string = SAMPErrorMsg(SAMPError);
d0 d1
«««««««««««««« PROCESSING UNKNOWN CHUNKS »»»»»»»»»»»»
When your UnknownChunk vector is called by OpenSampRead, it passes a
SeekOffset. This value is the number of bytes from the beginning of the file
to this chunk's ID, and can be used by your application to Seek() to this chunk
later. Your vector should store the chunk ID and SeekOffset for later process-
ing after OpenSampRead returns. The idea is to Seek() to the chunk and process
it, perhaps before or after you ReadWaves(), ReadNames(), LoadPlaymap(),
MixPlaymap(), and certainly before you CloseSamp(). The DOS fileHandle can be
found in the library SAMPInfo's Handle field. Do not do any Seek() or Read()
from within this vector!!! The ChunkSize passed to your vector does not
count the standard, 8 byte IFF chunkID and chunkSize fields that all IFF
chunks must start with.